﻿using GiteeOpenSdk.Common;
using GiteeOpenSdk.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace GiteeOpenSdk.Services
{
    /// <summary>
    /// Gitee请求
    /// </summary>
    public class GiteeCommonApi
    {
        /// <summary>
        /// 请求接口
        /// </summary>
        private static readonly string ApiUrl = "https://gitee.com/api/v5";

        /// <summary>
        /// 应用ID
        /// </summary>
        public string ClientId { get; set; }
        /// <summary>
        /// 应用密钥
        /// </summary>
        public string ClientSecret { get; set; }
        /// <summary>
        /// 回调Url
        /// </summary>
        public string RedirectUri { get; set; }
        /// <summary>
        /// 授权码
        /// </summary>
        public string AccessToken { get; set; }
        protected static HttpClient client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) };
        public GiteeCommonApi()
        {
        }
        public GiteeCommonApi(string clientId, string clientSecret, string accessToken)
        {
            ClientId = clientId;
            ClientSecret = clientSecret;
            AccessToken = accessToken;
        }
        protected async Task<ResponseModels<TResult>> ExecutesAsync<TModel, TResult>(string path, TModel model) where TModel : GiteeRequestModel where TResult : GiteeResponseModel
        {
            try
            {
                var response = await ExeAsync(path, model);
                var jsonResult = await response.Content.ReadAsStringAsync();
                var Result = new ResponseModels<TResult>
                {
                    StatusCode = response.StatusCode
                };
                if (response.IsSuccessStatusCode)
                {
                    var result = JsonConvert.DeserializeObject<List<TResult>>(jsonResult);
                    Result.ResponseContent = result;
                }
                else
                {
                    var jObject = JObject.Parse(jsonResult);
                    var errorMessage = "";
                    if (jObject.TryGetValue("message", out var errorResponse))
                    {
                        errorMessage = errorResponse.ToString();
                    }
                    Result.ErrorMessage = errorMessage;
                    Console.WriteLine("请求错误：" + response.ReasonPhrase + ":" + response.StatusCode);
                }
                return Result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + "\n" + e.StackTrace);
                return new ResponseModels<TResult>
                {
                    StatusCode = System.Net.HttpStatusCode.InternalServerError,
                    ErrorMessage = "SDK内部错误:" + e.Message
                };
            }
        }
        protected async Task<ResponseModel<TResult>> ExecuteAsync<TModel, TResult>(string path, TModel model) where TModel : GiteeRequestModel where TResult : GiteeResponseModel
        {
            try
            {
                var response = await ExeAsync(path, model);
                var jsonResult = await response.Content.ReadAsStringAsync();
                var Result= new ResponseModel<TResult>
                {
                    StatusCode = response.StatusCode
                };
                if (response.IsSuccessStatusCode)
                {
                    var result = JsonConvert.DeserializeObject<TResult>(jsonResult);
                    Result.ResponseContent = result;
                }
                else
                {
                    var jObject = JObject.Parse(jsonResult);
                    var errorMessage = "";
                    if (jObject.TryGetValue("message", out var errorResponse))
                    {
                        errorMessage = errorResponse.ToString();
                    }
                    Result.ErrorMessage = errorMessage;
                    Console.WriteLine("请求错误：" + response.ReasonPhrase + ":" + response.StatusCode);
                }
                return Result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + "\n" + e.StackTrace);
                return new ResponseModel<TResult>
                {
                    StatusCode = System.Net.HttpStatusCode.InternalServerError,
                    ErrorMessage = "SDK内部错误:" + e.Message
                };
            }
        }

        private async Task<HttpResponseMessage> ExeAsync<TModel>(string path, TModel model)
        {
            //if (string.IsNullOrEmpty(ClientId) || string.IsNullOrEmpty(ClientSecret))
            //{
            //    throw new Exception("请检查是否设置ClientId、ClientSecret");
            //}
            var dicQuery = new Dictionary<string, string>();
            var dicBody = new Dictionary<string, string>();

            //获取请求方法
            var requestMethod = model.ToRequestMethod();

            Type type = model.GetType();
            PropertyInfo[] PropertyList = type.GetProperties();
            foreach (PropertyInfo item in PropertyList)
            {
                string name = item.Name;
                string srcName = item.ToJsonInfo();

                object value = item.GetValue(model, null);
                if (value != null)
                {
                    //获取请求类型
                    var requestType = item.ToRequestType();
                    if (requestType == "path")
                    {
                        path = path.Replace($"{{{srcName}}}", value.ToString());
                    }
                    else if (requestType == "query")
                    {
                        dicQuery.Add(srcName, value.ToString());
                    }
                    else if (requestType == "formData")
                    {
                        dicBody.Add(srcName, value.ToString());
                    }
                    else //todo:报错
                    {

                    }
                }
            }

            var url = Path.Combine(ApiUrl, path);
            if (dicQuery.Count > 0)
            {
                url += "?" + dicQuery.ParseToString();
            }

            var jsonBody = JsonConvert.SerializeObject(dicBody);
            var data = new StringContent(jsonBody, Encoding.UTF8, "application/json");

            HttpResponseMessage response;
            if (requestMethod == "GET")
            {
                response = await client.GetAsync(url);
            }
            else if (requestMethod == "POST")
            {
                response = await client.PostAsync(url, data);
            }
            else if (requestMethod == "PATCH")
            {
                response = await client.PatchAsync(url, data);
            }
            else if (requestMethod == "DELETE")
            {
                response = await client.DeleteAsync(url);
            }
            else if (requestMethod == "PUT")
            {
                response = await client.PutAsync(url, data);
            }
            else
            {
                //todo:异常处理
                throw new Exception("错误的方法");
            }

            return response;
        }
    }
}